`timescale 1ns/1ps
`default_nettype none
// -----------------------------------------------------------------------------
// controller.v —— 指令译码控制（RV32I 子集：ADDI/ADD/SUB/LW/SW/JAL）
// 端口：
//   instr     [in] 32-bit 指令字（来自 IF/ID）
//   regwrite  [out] 是否写回寄存器堆（R/I/LW/JAL 为 1，SW/分支为 0）
//   alusrc    [out] EX.B 端选择：1=立即数（ADDI/LW/SW），0=rs2（R 型）
//   alu_ctrl  [out] ALU 操作码：0000=ADD，0001=SUB（可继续扩展）
//   memread   [out] dmem 读使能（LW）
//   memwrite  [out] dmem 写使能（SW）
//   memtoreg  [out] 写回选择：1=内存数据（LW），0=ALU/其他（R/I/JAL）
//   jal       [out] 本条是否为 JAL（EX 级用于触发 pc 重定向与流水清空）
//   branch    [out] 本条是否为 BEQ（EX 判定是否跳转）
// -----------------------------------------------------------------------------
module controller(
    input  wire [31:0] instr,
    output wire        regwrite,
    output wire        alusrc,
    output wire [3:0]  alu_ctrl,
    output wire        memread,
    output wire        memwrite,
    output wire        memtoreg,
    output wire        jal,
    output wire        branch,
    output wire        jalr        // ★ 新增：JALR 标志
);
    // 基本字段
    wire [6:0] opcode = instr[6:0];
    wire [2:0] funct3 = instr[14:12];
    wire [6:0] funct7 = instr[31:25];

    // ================= 指令类型侦测 =================
    // I-type: ADDI
    wire is_addi = (opcode == 7'b0010011) && (funct3 == 3'b000);

    // R-type: ADD/SUB
    wire is_rtype = (opcode == 7'b0110011) && (funct3 == 3'b000);
    wire is_add   = is_rtype && (funct7 == 7'b0000000);
    wire is_sub   = is_rtype && (funct7 == 7'b0100000);

    // Loads/Stores（这里只做 LW/SW）
    wire is_lw    = (opcode == 7'b0000011) && (funct3 == 3'b010); // LW
    wire is_sw    = (opcode == 7'b0100011) && (funct3 == 3'b010); // SW

    // Jumps
    wire is_jal   = (opcode == 7'b1101111); // JAL (J-type)

    // Branch（此处实现 BEQ）
    wire is_beq   = (opcode == 7'b1100011) && (funct3 == 3'b000);
    wire is_jalr  = (opcode == 7'b1100111) && (funct3 == 3'b000); // ★ JALR

    // ================= 控制信号输出 =================
    // 寄存器写回：R/I/LW/JAL 写回，SW 不写回
    assign regwrite = is_addi | is_add | is_sub | is_lw | is_jal | is_jalr;

    // ALU 第二操作数来源：ADDI/LW/SW 用立即数，其余（R 型）用 rs2
    assign alusrc   = is_addi | is_lw | is_sw | is_jalr;

    // ALU 操作：默认加法；SUB 指定减法
    assign alu_ctrl = is_sub ? 4'b0001 : 4'b0000;

    // 数据存储器接口
    assign memread  = is_lw;
    assign memwrite = is_sw;

    // 写回多路选择：仅 LW 从内存写回；其余（R/I/JAL）从 ALU/pc+4
    assign memtoreg = is_lw;

    // 跳转标志：JAL
    assign jal      = is_jal;
    assign branch   = is_beq;
    assign jalr     = is_jalr;

endmodule
